import React, { FC, useCallback } from 'react';
import { Editor } from 'slate';
import { useSlate } from 'slate-react';
import { Dropdown, Menu } from 'antd';
import { css } from 'emotion';

import { isMarkActive, toggleMark, toggleBlock, CustomText } from '@/core';

import { MenuIcon } from '../../component';
import { DropdownData, icons } from '../../share';
import { MenuItemValues } from './data';

interface DropdownOverlay {
  dropdownData: DropdownData;
  onMouseDown: (value: string) => void;
  currentSelected?: string;
}

const DropdownOverlay: FC<DropdownOverlay> = (props) => {
  const { dropdownData, onMouseDown, currentSelected } = props;
  return (
    <Menu
      className={css`
        overflow: auto;
        max-height: 200px;
        border: 1px solid #d7d7d7;
      `}
      defaultSelectedKeys={currentSelected ? [currentSelected] : undefined}
      onClick={({ key }) => onMouseDown(key)}
    >
      {Object.keys(dropdownData).map((key) => {
        const { name, icon } = dropdownData[key];
        return (
          <Menu.Item
            key={key}
            className={css`
              user-select: none;
            `}
          >
            {icon ? <span style={{ verticalAlign: '-webkit-baseline-middle' }}>{icons[icon]()}</span> : null}
            {name}
          </Menu.Item>
        );
      })}
    </Menu>
  );
};

interface BlockDropdownProps {
  text: string;
  dropdownData: DropdownData;
}

export const BlockDropdown: FC<BlockDropdownProps> = (props) => {
  const { text, dropdownData } = props;
  const editor = useSlate();
  const onMouseDown = useCallback(
    (value) => {
      toggleBlock(editor, value);
    },
    [editor],
  );
  return (
    <>
      <Dropdown
        overlay={<DropdownOverlay onMouseDown={onMouseDown} dropdownData={dropdownData} />}
        placement="bottomLeft"
        arrow
        destroyPopupOnHide
      >
        <MenuIcon text={text} dropdown={true} />
      </Dropdown>
    </>
  );
};

interface MarkDropdownProps {
  format: 'fontSize' | 'fontFamily';
  dropdownData: DropdownData;
  text: string;
}

function getNameByValue(value: string, dropdownData: DropdownData) {
  for (const key in dropdownData) {
    if (dropdownData[key].value === value) {
      return dropdownData[key].name;
    }
  }
  return '';
}

export const MarkDropdown: FC<MarkDropdownProps> = (props) => {
  const { text, dropdownData, format } = props;
  const editor = useSlate();
  const marks = Editor.marks(editor) as CustomText;
  const onMouseDown = useCallback(
    (value) => {
      toggleMark(editor, format, dropdownData[value].value);
    },
    [editor, format],
  );
  const selected = String(marks && marks[format]);
  const textDescription = String(getNameByValue(marks && (marks[format] as string), dropdownData) || text);
  return (
    <>
      <Dropdown
        overlay={<DropdownOverlay dropdownData={dropdownData} onMouseDown={onMouseDown} currentSelected={selected} />}
        placement="bottomLeft"
        destroyPopupOnHide
        arrow
      >
        <MenuIcon active={isMarkActive(editor, format)} text={textDescription} dropdown={true} iconValue={MenuItemValues[format]} />
      </Dropdown>
    </>
  );
};
